use std::sync::Mutex;
use tauri::State;
use serde_json::Value;
use tauri::{Manager};
use std::{fs, path::PathBuf};
use flate2::read::GzDecoder;
use tar::Archive;

mod models;
mod log_parser;
mod db_service;

use models::{LogEntry, AnalysisCase, ImportOptions, LogFile};
use log_parser::LogParser;
use db_service::DatabaseService;

// 全局数据库服务
struct AppState {
    db: Mutex<DatabaseService>,
}

// 导入日志文件
#[tauri::command]
async fn import_log_file(
    state: State<'_, AppState>,
    file_path: String,
    options: ImportOptions,
) -> Result<Value, String> {
    let parser = LogParser::new(options);
    let entries = parser.parse_file(&file_path)
        .map_err(|e| e.to_string())?;
    
    let mut db = state.db.lock().unwrap();
    db.insert_log_entries(&entries)
        .map_err(|e| e.to_string())?;
    
    // 保存文件信息
    let file_info = LogFile {
        id: None,
        name: std::path::Path::new(&file_path)
            .file_name()
            .and_then(|n| n.to_str())
            .unwrap_or("unknown")
            .to_string(),
        path: file_path.clone(),
        size: std::fs::metadata(&file_path)
            .map(|m| m.len())
            .unwrap_or(0),
        imported_at: chrono::Utc::now(),
        entry_count: entries.len() as i64,
    };
    
    db.insert_log_file(&file_info)
        .map_err(|e| e.to_string())?;
    
    Ok(serde_json::json!({
        "success": true,
        "entries_count": entries.len(),
        "file_info": file_info
    }))
}

// 获取日志条目
#[tauri::command]
async fn get_log_entries(
    state: State<'_, AppState>,
    limit: Option<i64>,
    offset: Option<i64>,
) -> Result<Vec<LogEntry>, String> {
    let db = state.db.lock().unwrap();
    db.get_log_entries(limit, offset)
        .map_err(|e| e.to_string())
}

// 获取日志文件列表
#[tauri::command]
async fn get_log_files(state: State<'_, AppState>) -> Result<Vec<LogFile>, String> {
    let db = state.db.lock().unwrap();
    db.get_log_files()
        .map_err(|e| e.to_string())
}

/// 解压 .tar 或 .tar.gz 到临时目录并返回解压后的根路径
#[tauri::command]
async fn extract_workspace_archive(app: tauri::AppHandle, archive_path: String) -> Result<String, String> {
    let temp_dir = app.path().app_cache_dir().map_err(|e| e.to_string())?;
    let target_dir = PathBuf::from(&temp_dir).join(format!("extracted_{}", chrono::Utc::now().timestamp()));
    fs::create_dir_all(&target_dir).map_err(|e| e.to_string())?;

    let path = PathBuf::from(&archive_path);
    let file = fs::File::open(&path).map_err(|e| e.to_string())?;

    // 支持 .tar.gz / .tgz 和 .tar
    let lower = path.to_string_lossy().to_lowercase();
    if lower.ends_with(".tar.gz") || lower.ends_with(".tgz") || lower.ends_with(".gz") {
        let gz = GzDecoder::new(file);
        let mut ar = Archive::new(gz);
        ar.unpack(&target_dir).map_err(|e| e.to_string())?;
    } else if lower.ends_with(".tar") {
        let mut ar = Archive::new(file);
        ar.unpack(&target_dir).map_err(|e| e.to_string())?;
    } else {
        return Err("不支持的归档格式（仅支持 .tar/.tar.gz）".into());
    }

    Ok(target_dir.to_string_lossy().to_string())
}

// 创建分析用例
#[tauri::command]
async fn create_analysis_case(
    state: State<'_, AppState>,
    case: AnalysisCase,
) -> Result<i64, String> {
    let db = state.db.lock().unwrap();
    db.insert_analysis_case(&case)
        .map_err(|e| e.to_string())
}

// 获取分析用例列表
#[tauri::command]
async fn get_analysis_cases(state: State<'_, AppState>) -> Result<Vec<AnalysisCase>, String> {
    let db = state.db.lock().unwrap();
    db.get_analysis_cases()
        .map_err(|e| e.to_string())
}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    // 初始化数据库
    let db_path = "logvision.db";
    let db_service = DatabaseService::new(db_path)
        .expect("Failed to initialize database");
    
    let app_state = AppState {
        db: Mutex::new(db_service),
    };

    tauri::Builder::default()
        .plugin(tauri_plugin_opener::init())
        .plugin(tauri_plugin_fs::init())
        .manage(app_state)
        .invoke_handler(tauri::generate_handler![
            import_log_file,
            get_log_entries,
            get_log_files,
            create_analysis_case,
            get_analysis_cases,
            extract_workspace_archive,
        ])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
